/* $RCSFile: PagingFull.cs $
 * Apache license v2 2011 by Christian Surieux
 * $Source: ?/ADNCRM.Core/UI/WebControls/PagingFull.cs $
 * $log$
 * Revision 6 2010/08/06 19:56:30  christian.surieux
 *   Added Log to All cs files
 */

using System;
using System.Collections;
using System.Collections.Specialized;
using System.Diagnostics;
using System.IO;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.HtmlControls;
using System.ComponentModel;
using System.Globalization;

using AddonNice.Helpers;
using AddonNice.Diagnostics;
using AddonNice.Settings;
using AddonNice.Configuration;

using Telerik.Web.UI;

using Trace2    =   System.Diagnostics.Trace;


namespace AddonNice.UI.WebControls
{

	/// <summary>
	/// The paging control is used to display paging options for controls that
	/// page through data. This control is necessary since some data rendering 
	/// controls, such as the DataList, do not support paging and it must be 
	/// a custom implementation.
	/// </summary>
	public class PagingFull : Paging
	{
		// Controls
		LinkButton[] numericalLinkButtons;
        Label navigationText;
        PlaceHolder numericalPaging;


		/// <summary>
		/// Specifies the number of pages to display on each side of numerical pager
		/// </summary>
		[
		Description("Specifies the number of pages to display on each side of numerical pager.")
		]
		bool _UseNextPrev  =   true;
		public bool UseNextPrev 
		{
			get 
			{
                return _UseNextPrev;
			}
			set 
			{
                _UseNextPrev =   value;
			}
		}

        
		/// <summary>
		/// Specifies the number of pages to display on each side of numerical pager
		/// </summary>
		[
		Description("Specifies the number of pages to display on each side of numerical pager.")
		]
		int _ItemsToDisplay  =   3;
		public int ItemsToDisplay 
		{
			get 
			{
                return _ItemsToDisplay;
			}
			set 
			{
                if ( value < 0 )
                    return;
                _ItemsToDisplay  =   value;
			}
		}

        
		/// <summary>
		/// Specifies the number of pages to display near the current page in numerical pager.
		/// </summary>
		[
		Description("Specifies the number of pages to display near the current page in numerical pager.")
		]
		int _ItemsToDisplayNear  =   2;
		public int ItemsToDisplayNear 
		{
			get 
			{
                return _ItemsToDisplayNear;
			}
			set 
			{
                if ( value < 0 )
                    return;
                _ItemsToDisplayNear  =   value;
			}
		}

        
        
        /// <summary>
		/// Specifies the current page in the index. Starting value at zero.
		/// </summary>
		[
		Description("Specifies the current page in the index.")
		]
		private int PageIndex 
		{
			get 
			{
                return PageNumber-1;
			}
			set 
			{
                if ( value < 0 )
                    return;
                if ( value >= PageCount )
                    return;
				PageNumber = value+1;
                ResetControls();
			}
		}

        /// <summary>
		/// Current page number, we must reset control list to catch a page change
		/// </summary>
		public override int PageNumber
		{
			get 
			{
                return base.PageNumber;
			}
			set
			{
                if ( UseNextPrev )
                    base.PageNumber =   value;
                else ViewState["PageNumber"]  =   value;
                ResetControls();
			}
		}
        
            
		/// <summary>
		/// Event raised when a new index is selected from the paging control
		/// </summary>
		private void PageIndex_Click(Object sender, EventArgs e) 
		{
			string requestedPage    =   ((LinkButton) sender).CommandArgument;
			if ( requestedPage.Length > 0 )
			{
				PageIndex           =   Convert.ToInt32(requestedPage);
                RefreshButtons();
                OnMoveHandler(e);
			}
		}

        
        public PagingFull() 
		{
		}

        void ResetControls()
        {
            ChildControlsCreated    =   false;
        }

        protected override void RefreshButtons()
		{
            EnsureChildControls();
			
            // enable/disable the nav controls based on the current context
			// we should only show the first button if we're NOT on the first page already
            if (UseNextPrev)
            {
                btnFirst.Enabled = (PageNumber != 1);
                btnPrev.Enabled = (PageNumber > 1);
                btnNext.Enabled = (PageNumber < PageCount);
                btnLast.Enabled = (PageNumber != PageCount);
                //Update labels
                lblPageCount.Text = PageCount.ToString();
            }

            // Don't display when flag set or no records
			if ( PageCount <= 1 && ( HideOnSinglePage || RecordCount == 0 ))
			{
                Visible                 =   false;
			}
			else
			{
                Visible                 =   true;
                if (UseNextPrev)
                {
                    btnFirst.Visible = true;
                    btnPrev.Visible = true;
                    btnNext.Visible = true;
                    btnLast.Visible = true;
                    lblof.Visible = true;
                    lblPageCount.Visible = true;
                    tbPageNumber.Visible = true;
                }
                navigationText.Visible  =   true;
                numericalPaging.Visible =   true;
			}
		}

		/// <summary>
		/// This event handler adds the children controls and is resonsible
		/// for determining the template type used for the control.
		/// </summary>
		protected override void CreateChildControls() 
		{
            if ( WebControlsTraceSwitch.Sw.TraceVerbose )
                Trace2.WriteLine( "[V]Paging CreateChildControls BEG.",WebControlsTraceSwitch.Sw.Info);
            Controls.Clear();

			// How many link buttons do we need?
			numericalLinkButtons = new LinkButton[PageCount];

			// Add the control to display navigation
			// Do we have multiple pages to display?
			navigationText          =   new Label();
			navigationText.CssClass =   "normalTextSmallBold";
            navigationText.Text     =   LocalizeHelper.Localize("GOTO_PAGE","Goto to page:");

			Controls.Add(navigationText);
            
			// Numerical Paging
			numericalPaging         =   new PlaceHolder();
			int linkButtonsToCreate =   PageCount;


			// Prepare all the potential link buttons
			for (int i = 0; i < linkButtonsToCreate ; i++) 
			{
				numericalLinkButtons[i]                 =   new LinkButton();
				numericalLinkButtons[i].CssClass        =   "normalTextSmallBold";
				numericalLinkButtons[i].Click           +=  new System.EventHandler(PageIndex_Click);
				numericalLinkButtons[i].Text            =   (i + 1).ToString("n0");
				numericalLinkButtons[i].ToolTip         =   navigationText.Text+" "+(i + 1).ToString("n0");
				numericalLinkButtons[i].CommandArgument =   i.ToString();
			}
            CreateNumericalPaging();
            if ( UseNextPrev )
                CreateNextPrev();
		}

		/// <summary>
		/// Controls how the numerical link buttons get rendered
		/// </summary>
		private void CreateNumericalPaging() 
		{
			int itemsToDisplay          =   ItemsToDisplay;
			int itemsToDisplayNear      =   ItemsToDisplayNear;
			int upperBoundPosition      =   (PageCount - 1);
            int _PageIndex              =   PageIndex;
			Label label;

            // Clear out the controls
			numericalPaging.Controls.Clear();
			if ( numericalLinkButtons.Length < itemsToDisplay )
				itemsToDisplay          =   numericalLinkButtons.Length;

            // Always display the first itemsToDisplay if available
            int lastIndex               =   0;
            int nextIndex               =   itemsToDisplay-1;
			for (int i = 0; i <= nextIndex; i++) 
			{
                if (i == _PageIndex)
                {
                    label           = new Label();
                    label.CssClass  = "normalTextSmallBold";
                    label.Text      = "[" + (i + 1).ToString("n0") + "]";
                    numericalPaging.Controls.Add(label);
                }
                else
                {
                    numericalPaging.Controls.Add(numericalLinkButtons[i]);
                }
				if ( i  != nextIndex ) 
				{
					label               =   new Label();
					label.CssClass      =   "normalTextSmallBold";
					label.Text          =   ", ";
					numericalPaging.Controls.Add(label);
				}
			}

			// is PageIndex in first half of pages
			if ( _PageIndex  <= upperBoundPosition/2 ) 
			{
                // display pages until PageIndex+itemsToDisplayNear
                lastIndex               =   nextIndex+1;
                nextIndex               =   _PageIndex + itemsToDisplayNear;
                if ( nextIndex > upperBoundPosition )
                    nextIndex   =   upperBoundPosition;
                bool addDash    =   false;
                if ( _PageIndex > (itemsToDisplayNear+itemsToDisplay) &&
                    (nextIndex - lastIndex) >= 2 * itemsToDisplayNear)
                {
                    addDash =   true;
                    label = new Label();
                    label.CssClass = "normalTextSmallBold";
                    label.Text = " ... ";
                    numericalPaging.Controls.Add(label);
                    lastIndex       =   nextIndex - 2*itemsToDisplayNear;
                }
				for (int i = lastIndex; i <= nextIndex; i++) 
				{
                    if ( !addDash || (i != lastIndex) )
                    {
                        label = new Label();
                        label.CssClass = "normalTextSmallBold";
                        label.Text = ", ";
                        numericalPaging.Controls.Add(label);
                    }
                    if ( i == _PageIndex)
                    {
                        label = new Label();
                        label.CssClass = "normalTextSmallBold";
                        label.Text = "[" + (i+ 1).ToString("n0") + "]";
                        numericalPaging.Controls.Add(label);
                    }
                    else
                    {
                        numericalPaging.Controls.Add(numericalLinkButtons[i]);
                    }
				}
			}
			// Insert the ellipses or a trailing comma if necessary
            if (nextIndex != upperBoundPosition)
            {
                label = new Label();
                label.CssClass = "normalTextSmallBold";
                if ( nextIndex +1+ itemsToDisplay >= upperBoundPosition )
                {
                    label.Text = ", ";
                }
                else
                {
                    label.Text = " ... ";
                }
                numericalPaging.Controls.Add(label);
            }
			// else if pageIndex in in second half of pages
			if ( _PageIndex  > upperBoundPosition/2 ) 
			{
                // display pages from PageIndex-itemsToDisplayNear
                lastIndex       =   nextIndex+1;
                for ( int i = itemsToDisplayNear ; i >= 0 ; i--)
                {
                    if ( (_PageIndex - i) > lastIndex )
                    {
                        lastIndex               =   _PageIndex - i;
                        break;
                    }
                }
                nextIndex               =   upperBoundPosition;
                bool addDash            =   false;
                if ((nextIndex - lastIndex) > 2 * itemsToDisplayNear)
                {
                    nextIndex   =   lastIndex + itemsToDisplayNear;
                    if ( nextIndex < _PageIndex+itemsToDisplayNear )
                        nextIndex   =   _PageIndex+itemsToDisplayNear;
                    if ( _PageIndex+itemsToDisplayNear+ItemsToDisplay >= upperBoundPosition )
                        nextIndex               =   upperBoundPosition;
                    else addDash =   true;
                }
				for (int i = lastIndex; i <= nextIndex; i++) 
				{
                    if ( i != lastIndex )
                    {
					    label               =   new Label();
					    label.CssClass      =   "normalTextSmallBold";
					    label.Text          =   ", ";
                        numericalPaging.Controls.Add(label);
                    }
                    if (i == _PageIndex)
                    {
                        label               = new Label();
                        label.CssClass      = "normalTextSmallBold";
                        label.Text          = "[" + (i+ 1).ToString("n0") + "]";
                        numericalPaging.Controls.Add(label);
                    }
                    else
                    {
                        numericalPaging.Controls.Add(numericalLinkButtons[i]);
                    }
				}
                if (addDash)
                {
                    label = new Label();
                    label.CssClass = "normalTextSmallBold";
                    label.Text = " ... ";
                    numericalPaging.Controls.Add(label);
                }

			}

			// Always display the last itemsToDisplay if available
			if ( nextIndex < upperBoundPosition ) 
			{
                lastIndex       =   nextIndex+1;
                while ( lastIndex <= ( upperBoundPosition-itemsToDisplay) ) 
                    lastIndex++;
                nextIndex   =   upperBoundPosition;
				for (int i = lastIndex ; i <= nextIndex ; i++) 
				{
					numericalPaging.Controls.Add(numericalLinkButtons[i]);
					if ( i != upperBoundPosition ) 
					{
						Label tmp           =   new Label();
						tmp.CssClass        =   "normalTextSmallBold";
						tmp.Text            =   ", ";
						numericalPaging.Controls.Add( tmp );
					}
				}
			}
            if (UseNextPrev)
            {
                Literal spc     = new Literal();
                spc.Text        = "&nbsp;";
    		    numericalPaging.Controls.Add(spc);
            }
            Controls.Add(numericalPaging);
		}      


        protected override void RenderContents(HtmlTextWriter writer)
        {
            if ( WebControlsTraceSwitch.Sw.TraceVerbose )
                Trace2.WriteLine( "[V]PagingFull RenderContents BEG.",WebControlsTraceSwitch.Sw.Info);
            try
            {
                AddAttributesToRender(writer);

                writer.AddAttribute(HtmlTextWriterAttribute.Cellpadding, CellPadding.ToString(), false);
                writer.AddAttribute(HtmlTextWriterAttribute.Cellspacing, CellSpacing.ToString(), false);
                writer.RenderBeginTag(HtmlTextWriterTag.Table);

                writer.RenderBeginTag(HtmlTextWriterTag.Tr);

                writer.RenderBeginTag(HtmlTextWriterTag.Td);
				navigationText.RenderControl(writer);
                writer.RenderEndTag();

                writer.RenderBeginTag(HtmlTextWriterTag.Td);
				numericalPaging.RenderControl(writer);
                writer.RenderEndTag();
                
                if ( UseNextPrev )
                    RenderPrevNext(writer);

                writer.RenderEndTag(); //tr

                writer.RenderEndTag(); //table
            }
            catch (Exception ex)
            {
                if ( WebControlsTraceSwitch.Sw.TraceError )
                    Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]PagingFull RenderContents ex: {0}",ex),WebControlsTraceSwitch.Sw.Info);
                throw;
            }
             if ( WebControlsTraceSwitch.Sw.TraceVerbose )
                Trace2.WriteLine( "[V]PagingFull RenderContents END.",WebControlsTraceSwitch.Sw.Info);
       }
	}
}
